const { query } = require('../database/connection');

// 将 JS 日期或 ISO 字符串转换为 MySQL DATETIME 格式：YYYY-MM-DD HH:MM:SS
function toMySQLDateTime(input) {
  if (!input) return null;
  const d = input instanceof Date ? input : new Date(input);
  if (isNaN(d)) return null;
  const pad = (n) => String(n).padStart(2, '0');
  const yyyy = d.getFullYear();
  const MM = pad(d.getMonth() + 1);
  const dd = pad(d.getDate());
  const hh = pad(d.getHours());
  const mm = pad(d.getMinutes());
  const ss = pad(d.getSeconds());
  return `${yyyy}-${MM}-${dd} ${hh}:${mm}:${ss}`;
}

class LogModel {
  static async logAccess({ method, path, status, duration_ms, ip, ua, userId = null, phone = null, time = null }) {
    try {
      const timeValue = toMySQLDateTime(time || new Date());
      await query(
        `INSERT INTO access_logs (method, path, status, duration_ms, ip, ua, user_id, phone, \`time\`)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, COALESCE(?, NOW()))` ,
        [method, path, status, duration_ms, ip, ua, userId, phone, timeValue]
      );
    } catch (e) {
      console.warn('[logAccess] 写入失败:', e?.message || e);
    }
  }

  static async logAction({ level = 'INFO', type = 'action', action, method, path, ip, ua, userId = null, phone = null, time = null, meta = {} }) {
    try {
      await query(
        `INSERT INTO action_logs (level, type, action, method, path, ip, ua, user_id, phone, meta, created_at)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
        [level, type, action, method, path, ip, ua, userId, phone, JSON.stringify(meta || {})]
      );
    } catch (e) {
      console.warn('[logAction] 写入失败:', e?.message || e);
    }
  }

  static async ensureProxyLogsTable() {
    const sql = `
      CREATE TABLE IF NOT EXISTS proxy_logs (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        request_id VARCHAR(128) NULL,
        method VARCHAR(16) NULL,
        path VARCHAR(1024) NULL,
        headers LONGTEXT NULL,
        body LONGTEXT NULL,
        response_status INT NULL,
        response_body LONGTEXT NULL,
        duration INT NULL,
        error_message TEXT NULL,
        created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY idx_request_id (request_id),
        KEY idx_created_at (created_at)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    `;
    try {
      await query(sql);
    } catch (e) {
      // 创建失败不阻断主流程
      console.warn('[ensureProxyLogsTable] 创建失败:', e?.message || e);
    }
  }

  static async logProxy({ request_id = null, method, path, headers = {}, body = null, response_status = null, response_body = null, duration = null, error_message = null }) {
    const doInsert = async () => {
      await query(
        `INSERT INTO proxy_logs (request_id, method, path, headers, body, response_status, response_body, duration, error_message)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          request_id,
          method,
          path,
          JSON.stringify(headers || {}),
          typeof body === 'string' ? body : JSON.stringify(body || null),
          response_status,
          typeof response_body === 'string' ? response_body : JSON.stringify(response_body || null),
          duration,
          error_message,
        ]
      );
    };
    try {
      await doInsert();
    } catch (e) {
      if (e && (e.code === 'ER_NO_SUCH_TABLE' || /doesn't exist/i.test(e.message))) {
        await LogModel.ensureProxyLogsTable();
        try {
          await doInsert();
          return;
        } catch (e2) {
          console.warn('[logProxy] 重试写入失败:', e2?.message || e2);
        }
      }
      console.warn('[logProxy] 写入失败:', e?.message || e);
    }
  }
}

module.exports = LogModel;
